#ifndef NETLIB_MUTEX_H
#define NETLIB_MUTEX_H

// 互斥锁

#include "CurrentThread.h"
#include "noncopyable.h"
#include <assert.h>
#include <pthread.h>


#if defined(__clang__) && (!defined(SWIG))
#define THREAD_ANNOTATION_ATTRIBUTE__(x)   __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x)   // no-op
#endif

#define CAPABILITY(x) \
  THREAD_ANNOTATION_ATTRIBUTE__(capability(x))

#define SCOPED_CAPABILITY \
  THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)

#define GUARDED_BY(x) \
  THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))

#define PT_GUARDED_BY(x) \
  THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))

#define ACQUIRED_BEFORE(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))

#define ACQUIRED_AFTER(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))

#define REQUIRES(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))

#define REQUIRES_SHARED(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))

#define ACQUIRE(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))

#define ACQUIRE_SHARED(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))

#define RELEASE(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))

#define RELEASE_SHARED(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))

#define TRY_ACQUIRE(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))

#define TRY_ACQUIRE_SHARED(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))

#define EXCLUDES(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))

#define ASSERT_CAPABILITY(x) \
  THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))

#define ASSERT_SHARED_CAPABILITY(x) \
  THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))

#define RETURN_CAPABILITY(x) \
  THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))

#define NO_THREAD_SAFETY_ANALYSIS \
  THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)


#ifdef CHECK_PTHREAD_RETURN_VALUE

#ifdef NDEBUG
__BEGIN_DECLS
extern void __assert_perror_fail (int errnum,
                                  const char *file,
                                  unsigned int line,
                                  const char *function)
    noexcept __attribute__ ((__noreturn__));
__END_DECLS
#endif

#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret);         \
                       if (__builtin_expect(errnum != 0, 0))    \
                         __assert_perror_fail (errnum, __FILE__, __LINE__, __func__);})

#else

#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret);         \
                       assert(errnum == 0); (void) errnum;})

#endif

namespace netlib
{

class CAPABILITY("mutex") MutexLock : noncopyable // 不可拷贝
{
public:
    MutexLock() : holder_(0) // 初始化锁
    { MCHECK(pthread_mutex_init(&mutex_, NULL)); }

    ~MutexLock()
    {
        assert(holder_ == 0); // 只有当没有线程占有这把锁的时候，才能销毁互斥锁
        MCHECK(pthread_mutex_destroy(&mutex_));
    }

    bool isLockedByThisThread() const // 查询是否时当前线程持有锁
    { return holder_ == CurrentThread::tid(); }

    void assertLocked() const ASSERT_CAPABILITY(this) // 断言当前线程是否持有锁
    { assert(isLockedByThisThread()); }

    void lock() ACQUIRE() // 加锁
    {
        MCHECK(pthread_mutex_lock(&mutex_));
        assignHolder();
    }

    void unlock() RELEASE() // 解锁
    {
        unassignHolder();
        MCHECK(pthread_mutex_unlock(&mutex_));
    }

    pthread_mutex_t* getPthreadMutex() { return &mutex_; } // 获取互斥锁变量

private:
    friend class Condition; // 友元类

    class UnassignGuard : noncopyable // 内嵌类，不可拷贝
    {
    public:
        explicit UnassignGuard(MutexLock& owner)
        : owner_(owner)
        { owner_.unassignHolder(); }

        ~UnassignGuard() { owner_.assignHolder(); }

    private:
        MutexLock& owner_;

    }; // class UnassignGuard end

    void unassignHolder() { holder_ = 0; } // 修改所属线程ID为0，释放锁

    // 修改所属线程ID为当前线程tid，占用锁
    void assignHolder() { holder_ = CurrentThread::tid(); }

    pthread_mutex_t mutex_;     // 互斥锁
    pid_t holder_;              // 线程ID (tid)

}; // class MutexLock end


class SCOPED_CAPABILITY MutexLockGuard : noncopyable // RAII机制，智能管理锁
{
public:
    explicit MutexLockGuard(MutexLock& mutex) ACQUIRE(mutex) //传入引用
        : mutex_(mutex)
    {
        mutex_.lock();
    }

    ~MutexLockGuard() RELEASE()
    {
        mutex_.unlock();
    }

private:

    MutexLock& mutex_; // 引用，该类不管理互斥锁的生命周期

}; // class MutexLockGuard end

} // namespace netlib end

// 防止用户使用匿名或临时锁，将其匿名形式定义为错误来防止
#define MutexLockGuard(x) error "Missing guard object name"

#endif